/**
 * SBmenu v1.0.1
 * http://www.sbzsoft.com/
 * http://sbmenu.googlecode.com/
 * 
 * Copyright 2010, SBZsoft (c), Shlomi Bazak
 * Licensed under the GPL Version 3 license.
 * 
 * Date: Thu Nov 25 2010
 */
(function($){
	var defaults = {
			rtl: false, // true false
			vertical: false, // vertical, horizontal
			effect: "slide", // fade, slide, show
			activeClass: 'active', // the selected class
			effectTime: 500,
			minLiWidth: 100
	};
	
	var sbmenu = function(e, o){
		this.options = $.extend({}, defaults, o || {});
		if(e.nodeName.toUpperCase() == 'UL') this.list = $(e);
		else this.list = $(e).find("ul:first"); 
		this.list.addClass('sbmenu');
		if(this.options.rtl) { 
			this.list.children('li').css({'float': 'right'});
			this.list.find('a, span').css({'text-align': 'right'});
		}
		this.list_parent = this.list.parent();
		this.init();
		this.start();
	};
	
	sbmenu.fn = sbmenu.prototype = {
		sbmenu: '1.0.1',
		by:   'SBZsoft'
	};
	
	sbmenu.fn.extend = sbmenu.extend = $.extend;
	
	sbmenu.fn.extend({
		last_item : null,
		show_timeout : null,
		hide_timeout : null,
		o : this.options,
		timeout: 500,
		
		
		init: function() {
			if(this.options.vertical) this.list.addClass('vertical');
			var li = this.list.find('.' + this.options.activeClass + ":first");
			if(li.length){
				if(li.get(0).tagName.toLowerCase() != 'li') li = li.parent();
				while(!li.parent().hasClass('sbmenu')){
					li = li.parent().parent();
					li.children('a, span').addClass('activePath');
				}
			}
			this.initUL( this.list, 0 );
		},
		
		slideIn: function(el){
			if(!el || !el.length) return;
			var ef_time = this.options.effectTime / 2;
			var parent = el.parent();
			if(el.get(0).__slideSatge == 3) return;
			el.stop(true, false);
			if(!el.get(0).__slideSatge){ // The UL is closed
				var left = 0;
				if(el.width() < parent.width() && !this.options.rtl) left =  parent.width() - el.width();
				el.css(
						{// Before slide right animation starts
							height: parent.height()+'px',
							display: 'block', 
							left: left+'px',
							width: parent.width() +'px',
							'z-index': -10
						}
				);
				el.get(0).__slideSatge = 1;
			}
			if(el.get(0).__slideSatge == 1){
				el.animate(
						{ // The Slide right animation css
							height: parent.height()+'px', 
							left: this.options.rtl ? -el.get(0).__width+'px' : parent.width()+'px',
							width: el.get(0).__width+'px'
						}, ef_time, 
						function(){
							// After the Slide right animation
							el.get(0).__slideSatge = 2;
							el.css({'z-index': parent.parent().css('z-index'), overflow: ''});
							el.get(0).__slideSatge = 2;
							el.animate({height: el.get(0).__height + 'px'}, ef_time, function(){el.get(0).__slideSatge = 3;});
						});
			}
			if(el.get(0).__slideSatge == 2){
				el.animate({height: el.get(0).__height + 'px'}, ef_time, function(){el.get(0).__slideSatge = 3;});
			}
		},
		
		slideOut: function(el){
			var ef_time = this.options.effectTime / 2;
			var el_ht = el.get(0);
			var self = this;
			el.stop(true, false);
			if(el.get(0).__slideSatge >= 2){
				el.get(0).__slideSatge = 2;
				el.animate({height: el.parent().height() + 'px'}, ef_time, function(){el.get(0).__slideSatge = 1;});
				el.css({'z-index': el.parent().css('z-index')-600}).animate({left:0, width: el.parent().width(), height: el.parent().height()}, ef_time, function(){
					el.css('display', 'none');
					el.get(0).__slideSatge = 0;
				});		
			}
			if(el.get(0).__slideSatge == 1){
				var left = 0;
				if(el.width() < el.parent().width() && !this.options.rtl) left = el.parent().width() - el.width();
				var width = el.width() < el.parent().width() ? el.width() : el.parent().width();
				el.css({'z-index': el.parent().css('z-index')-600}).animate({left:0, width: width, height: el.parent().height()}, ef_time, function(){
					el.css('display', 'none');
					el.get(0).__slideSatge = 0;
				});	
			}
		},
		
		show_item: function(item){
			if(!item || !item.length) return;
			clearTimeout(item[0].timeOut);
			// the load hack.
			item.css({visibility: 'visible'});
			switch(this.options.effect){
					case "fade":
						item.fadeIn(this.options.effectTime);
						break;
					case "slide":
						if(!this.options.vertical && item.parent().parent().hasClass('sbmenu'))
							item.slideDown(this.options.effectTime);
						else
							this.slideIn(item);
						break;
					default:
						item.show(this.options.effectTime);
			}
		},
		
		hide_item: function(item){
			if(!item || !item.length) return;
			var self = this;
			item[0].timeOut = setTimeout(
				function(){
					switch(self.options.effect){
						case "fade":
							item.fadeOut(self.options.effectTime);
							break;
						case "slide":
							if(!self.options.vertical && item.parent().parent().hasClass('sbmenu'))
								item.slideUp(self.options.effectTime);
							else
								self.slideOut(item);
							break;
						default:
							item.hide(self.options.effectTime);
					}
				},
				this.timeout
			);
		},
		
		setDims : function(el, level){
			var dims = findMaxWidthHeight(el);
			var width = dims[0], height = dims[1];
			if(width < this.options.minLiWidth) width = this.options.minLiWidth;
			el.children('li').css('width', width + "px");
			if(level > 0 || this.options.vertical){
				el.css({width: width + "px", height: height + 'px'});
			}
			if(level > 0) el.children('li').children('ul').css('left', width + 'px');
			el.get(0).__width = width;
			
		},
		
		initUL: function(ul, level){
			this.setDims(ul, level);
			ul.get(0).__height = ul.height();
			if(!this.options.vertical && level == 1 && this.options.rtl && ul.width() != ul.parent().width()){
				var parent_width = ul.parent().width();
				var parent_left = ul.parent().position().left;
				ul.css({left: ( parent_width - ul.width()) + 'px'});
			}
			else if(level > 1 && this.options.rtl){
				ul.css({left: (-ul.width()) + 'px'});
			}
			var self = this;
			ul.children('li').each(function(){
				if($(this).children('ul').length)
					self.initUL($(this).children('ul'), level+1);
			});
		},
		
		start: function(){
			var self = this;
			this.list.find('ul').css({display: "none"}); // Opera Fix
			this.list.find('li').hover(
				function(){
					if($(this).children('ul').length){
						self.show_item($(this).children('ul'));
					}
				},
				function(){
					if($(this).children('ul').length)
						self.hide_item($(this).children('ul'));
				}
				
			);
		}
	});
	
	/**
	 * Private function to find the max width within the UL element.
	 * and the elements height; 
	 */
	function findMaxWidthHeight(ul){
		var width = 0;
		var height = 0;
		ul.children('li').each(function(){
			width = $(this).width() > width ? $(this).width() : width;
			height +=  $(this).height();
		});
		return [width, height];
	}
	
	$.fn.sbmenu = function(o){
		return this.each(function(){
			$this = $(this);
			if($this.data('sbmenu')) return;
			$this.data('sbmenu', new sbmenu(this, o));
		});
	};
})(jQuery);
